﻿using Knight.Models.Base;
using Knight.Models.Entity;
using Knight.Web.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Knight.Models.Services
{
    public class DbSettingApi : ServiceBase
    {
        //获取指定类型的缓存键
        string getCacheKey<T>() where T : SettingBase
        {
            return getCacheKey(typeof(T));
        }

        string getCacheKey(Type type)
        {
            var name = type.Name;
            return string.Format("EJ_SETTING_{0}", name);
        }

        /// <summary>
        /// 加载当前对象实体
        /// </summary>
        T loadSettings<T>(IEnumerable<Setting> settings) where T : SettingBase, new()
        {

            Dictionary<string, Setting> dic = new Dictionary<string, Setting>();
            foreach (var setting in settings)
            {
                string key = setting.Key.Split('|')[1];
                dic.Add(key, setting);
            }

            var type = typeof(T);
            var properties = type.GetProperties();

            T model = new T();

            foreach (var p in properties)
            {
                if (dic.ContainsKey(p.Name))
                {
                    try
                    {
                        p.SetValue(model, convertValue(p.PropertyType, dic[p.Name].Value), null);
                    }
                    catch
                    { }
                }
            }
            return model;
        }
        /// <summary>
        /// 获取当前设置对象所有的属性设置值
        /// </summary>
        List<Setting> getSettings(SettingBase setting)
        {
            var list = new List<Setting>();
            var type = setting.GetType();
            var properties = type.GetProperties();
            var groupName = setting.GetGroupName();
            foreach (var p in properties)
            {
                var val = p.GetValue(setting, null);

                var model = new Setting()
                {
                    Group = groupName,
                    Key = string.Format("{0}|{1}", groupName, p.Name),
                    UpdateTime = DateTime.Now
                };
                if (p.PropertyType.IsEnum)
                {
                    model.Value = (val == null ? null : Convert.ToInt32(val).ToString());
                }
                else
                {
                    model.Value = (val == null ? null : val.ToString());
                }
                list.Add(model);
            }
            return list;
        }

        /// <summary>
        /// 保存配置信息
        /// </summary>
        public bool SaveSetting(SettingBase setting)
        {
            //清除缓存
            var key = getCacheKey(setting.GetType());
            CacheHelper.RemoveCache(key);        
            var list = getSettings(setting);
            var service = new SettingService();
            var rep = service.SaveSetting(list);

            return rep.IsSuccess;
        }

        /// <summary>
        /// 值，根据指定类型转换
        /// </summary>
        /// <returns></returns>
        private object convertValue(Type type, string value)
        {
            if (type == typeof(string))
            {
                return value;
            }
            else if (type == typeof(int))
            {
                int result = 0;
                int.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(bool))
            {
                bool result = false;
                bool.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(DateTime))
            {
                DateTime result = DateTime.MinValue;
                DateTime.TryParse(value, out result);
                return result;
            }
            else if (type.IsEnum)
            {
                int result = 0;
                int.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(double))
            {
                double result = 0;
                double.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(decimal))
            {
                decimal result = 0;
                decimal.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(float))
            {
                float result = 0;
                float.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(long))
            {
                long result = 0;
                long.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(byte))
            {
                byte result = 0;
                byte.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(sbyte))
            {
                sbyte result = 0;
                sbyte.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(short))
            {
                short result = 0;
                short.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(ushort))
            {
                ushort result = 0;
                ushort.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(uint))
            {
                uint result = 0;
                uint.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(ulong))
            {
                ulong result = 0;
                ulong.TryParse(value, out result);
                return result;
            }
            else if (type == typeof(int?))
            {
                int result = 0;
                if (int.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(bool?))
            {
                bool result = false;
                if (bool.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(DateTime?))
            {
                DateTime result = DateTime.MinValue;
                if (DateTime.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(double?))
            {
                double result = 0;
                if (double.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(decimal?))
            {
                decimal result = 0;
                if (decimal.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(float?))
            {
                float result = 0;
                if (float.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(long?))
            {
                long result = 0;
                if (long.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(byte?))
            {
                byte result = 0;
                if (byte.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(sbyte?))
            {
                sbyte result = 0;
                if (sbyte.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(short?))
            {
                short result = 0;
                if (short.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(ushort?))
            {
                ushort result = 0;
                if (ushort.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(uint?))
            {
                uint result = 0;
                if (uint.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            else if (type == typeof(ulong?))
            {
                ulong result = 0;
                if (ulong.TryParse(value, out result))
                {
                    return result;
                }
                else
                {
                    return null;
                }
            }
            return value;
        }

        public T GetSertting<T>() where T : SettingBase, new()
        {
            var key = getCacheKey<T>();       
            var setting = CacheHelper.GetCache<T>(key) as T;
            if (setting == null)
            {
                string group = typeof(T).Name;
                //从数据库中获取指定的所有的配置项
                var service = new SettingService();
                var listRep = service.GetSettingsBy(group);
                if (listRep.IsSuccess)
                {
                    setting = loadSettings<T>(listRep.Models);
                    //加载缓存中
                    CacheHelper.WriteCache(setting, key);
                }
                else
                {
                    throw new ApplicationException(listRep.Message);
                }
            }
            return setting;
        }
    }
}
